import { BodySetup } from "utils/creep/CreepSetup";
import { ActionBase, ActionBaseOfCreep } from "../ActionBase";
import { priority } from "utils/constants/definetypes";
import { role_crossLevel } from "utils/constants/moveConstant";
import { PositionHelper } from "utils/position/PositionHelper";
import { TeamMoveUtils } from "utils/team/TeamMoveUtils";
import { TeamUtils } from "utils/team/TeamUtils";
import { UtilsHelper } from "utils/position/UtilsHelper";
import { ATeamCombat } from "GameLoop/WorldState/EntityManager/Entitys";
import { StationNetwork } from "GameLoop/Path/StationNetwork";

/**
 * 升级Action
 */
export class ActionTeamSquareMove  extends ActionBase<IActionCMD<"squareMove">>
{
    public execute(action: IActionCMD<"squareMove">): ActionCode 
    {
          // 有任务
            // 更新移动指令,方阵移动必须得是左上角。和寻路配对使用的,左上角的位置当旋转后就不确定了
        const entity = action.arg.entity;
        const arg = action.arg
        const anchor = entity.getAnchor();
        const creeps = entity.creeps;
        const nodememory = entity.getNodeMemory();
        const currentpos =   anchor;;
        if(nodememory.path == undefined ||  nodememory.path.path=="" || nodememory.path.path[(nodememory.path.index)] === undefined|| nodememory.path.path.length == 0)
        {
            this.initPath(arg.entity,currentpos,arg.goal.pos,[],arg.goal.range);
        }
        // 路径存在且 没有更换目标

        // 接着走路
        // 更新当前的移动指令
        // arg.entity.log("info",`directive 1`);
        if(nodememory.path)
        {
            if(!nodememory.path.NextDirections ||!nodememory.path.NextDirections[0])
            {
                // 没有move，则需要设置
                this.updateNextDirection(entity,nodememory.path);
            }
            // 存在移动指令。调用移动
            if(nodememory.path.NextDirections&& nodememory.path.NextDirections.length>0&& nodememory.path.NextDirections[0])
            {
                arg.entity.log("info",`directive  ${JSON.stringify(nodememory.path.NextDirections)}`);
                const poss = _.map(creeps,e=>e.pos);
                let isMove = false;
                if(entity.getAttackableCreeps().length>0)
                {
                    if(TeamMoveUtils.isSqareSafeMoveable(entity,nodememory.path.NextDirections[0],entity.getAnchor().roomName))
                    {
                        arg.entity.log("info",`${arg.entity.GUID()} State_MoveCloseTo  Safe move`);
                        isMove = true;
                    }
                }
                else
                {
                    if(TeamUtils.isSqareMoveable(entity,nodememory.path.NextDirections[0]))
                    {
                        arg.entity.log("info",`${arg.entity.GUID()} State_MoveCloseTo  move}`);
                        isMove = true;
                    }
                }
                if(isMove)
                {
                        arg.entity.log("info",`${arg.entity.GUID()} State_MoveCloseTo ${JSON.stringify(nodememory.path.NextDirections)}  疲劳:${JSON.stringify(_.map(creeps
                        ,e=>e.fatigue))}`);
                        entity.teamMove();
                }
                else
                {
                    // 如果无法移动需要重新寻路
                    if(nodememory.path.NextDirections)
                    {
                        let nextTeamPos =   _.map(poss,e=> UtilsHelper.GetDirectionPos(e, (nodememory.path!.NextDirections as any) [0] ))  ;
                        this.initPath(entity,currentpos,arg.goal.pos,nextTeamPos,arg.goal.range);
                        arg.entity.log("info",`不可抵达 ${arg.entity.GUID()} State_MoveCloseTo ${JSON.stringify(currentpos)} -> ${JSON.stringify(nextTeamPos)} 重新寻路path:${JSON.stringify(nodememory.path)}`);
                        this.updateNextDirection(entity,nodememory.path);
                    }

                }

            }
        }
        return 0;
    }

    private updateNextDirection(entity:ATeamCombat,path:ITeamPath)
    {
        if(entity.isFatigue())
        {
            return ;
        }
        const direct = parseInt( path.path[(path.index)]) as DirectionConstant;
        const nextDirectives:(DirectionConstant|0)[]= new Array(entity.creeps.length).fill(direct);
        if(direct === null ||direct === undefined)
        {
            path.NextDirections=undefined;
            return ;
        }
        if(nextDirectives.length>0)
        {
            path.NextDirections = nextDirectives;
        }
    }
    // 每次寻路都要避开敌方的攻击单位,不然就会一直重复寻路
    private initPath(entity:ATeamCombat,from:ObjectRef,To:ObjectRef,blockpos:RoomPosition[],range:number=1)
    {
        const blockCreeps:Creep[]=[];
        const creeps = entity.creeps;
        const nodememory = entity.getNodeMemory();
        
        for(const id of nodememory.blockCreeps)
        {
            const obj = Game.getObjectById(id);
            if(obj)
            {
                blockCreeps.push(obj);
            }
        }

        // entity.blockCreeps = _.map(blockCreeps,item=>item.id);
        const p_s = PositionHelper.Create(from);
        const p_e = PositionHelper.Create(To);
        let path: IPathCache|undefined=undefined;

        let block_positions:RoomPosition[]= this.getHostilesBlockPosition(entity);
        let isDestoryStructure = (from.roomName == To.roomName) && Game.rooms[To.roomName] && !Game.rooms[To.roomName].IsFriend();
        block_positions = block_positions.concat(_.map(blockCreeps,item=>item.pos));
       // if(entity.CreepEntities.length>2)
        if(blockpos.length==0)
        {
            path = StationNetwork.getInstance.PathFinder.searchArmyPath(p_s,{pos:p_e,range:range},block_positions,{ingoreDamage: entity.getTeamHealMax(),IsDestoryStructure:isDestoryStructure});
        }
        else
        {
            block_positions = block_positions.concat(blockpos);
            path = StationNetwork.getInstance.PathFinder.searchArmyPath(p_s,{pos:p_e,range:range},block_positions,{ingoreDamage: entity.getTeamHealMax(),maxOps:1000,IsDestoryStructure:isDestoryStructure});
        }
        nodememory.path={
            path:path.cache,
            index:0,
            startpos:from,
            goalpos:To
        }


        nodememory.path.path =   path.cache;
        nodememory.path.index = 0;
        nodememory.path.NextDirections=undefined;
        Memory.Debug[`${entity.GUID} 4人寻路路径 :`] = JSON.stringify(nodememory.path);
    }


    private getHostilesBlockPosition(entity:ATeamCombat)
    {
        const block_positions:Record<number,RoomPosition>={};
        // 避开房间内的攻击性单位
        const hostilesCache = global.world.PollHostiles(entity.roomName);
        if(hostilesCache)
        {
            for(let id in hostilesCache.hostileCreepAbility)
            {
                const hostCreep = Game.getObjectById(id as Id<Creep>);
                if(hostCreep)
                {
                    if(hostilesCache.hostileCreepAbility[3])
                    {
                        const poss = PositionHelper.findRingOfValidPosition (hostCreep.pos,3);
                        for(const e of poss)
                        {
                            block_positions[e.x+e.y*50]=e;
                        }
                    }
                    else  if(hostilesCache.hostileCreepAbility[1])
                    {
                        const poss =   PositionHelper.findRingOfValidPosition (hostCreep.pos,1);
                        for(const e of poss)
                        {
                            block_positions[e.x+e.y*50]=e;
                        }
                    }
                }
            }
        }
        return Object.values(block_positions)
    }
}